/**
 * 
 */
package com.oron3.bouncer.objects.shapes;


/**
 * ax+by+=y
 * 
 * @author Ofek
 *
 */

public class LineSegment implements Shape {
	private static final int RELATION_ON_LINE_SEGMENT = 0;
	private static final int RELATION_NOT_ON_LINE_SEGMENT = 1;
	private static final float TOLERANCE = 0.000001f;
	public final Point p2;
	public final Line line;
	private final Point segementVector;

	/**
	 * start at p1 in the direction of p2
	 * 
	 * @param p1
	 * @param p2
	 */
	public LineSegment(final Point p1, final Point p2) {
		line = new Line(p1, p2);
		this.p2 = p2;
		segementVector = new Vector(p2.sub(p1));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.oron3.bouncer.objects.GLObject#step(float)
	 */




	/*
	 * (non-Javadoc)
	 * 
	 * @see com.oron3.bouncer.objects.shapes.Shape#intersection(com.oron3.bouncer.objects.shapes.Shape)
	 */
	@Override
	public Intersection intersection(final Shape o) {
		throw new RuntimeException();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.oron3.bouncer.objects.shapes.Shape#intersects(com.oron3.bouncer.objects.shapes.Shape)
	 */
	@Override
	public boolean intersects(final Shape o) {
		throw new RuntimeException();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return line.toString() + " to " + p2;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.oron3.bouncer.objects.shapes.Shape#calcRelation(com.oron3.bouncer.objects.shapes.Shape)
	 */
	@Override
	public int describeRelation(final Shape o) {
		if ( o instanceof Point ) {
			final Point p = (Point) o;
			if ((line.p1.distance(p) + p2.distance(p) - line.p1.distance(p2))<=TOLERANCE) return RELATION_ON_LINE_SEGMENT;
			return RELATION_NOT_ON_LINE_SEGMENT;
		}
		else throw new IllegalArgumentException();
	}

	public float length() {
		return segementVector.length();
	}

	/* (non-Javadoc)
	 * @see com.oron3.bouncer.objects.shapes.Shape#isInside(com.oron3.bouncer.objects.shapes.Shape)
	 */
	@Override
	public boolean isInside(final Shape o) {
		return describeRelation(o)==RELATION_ON_LINE_SEGMENT;
	}

	/**
	 * http://ocw.mit.edu/courses/mathematics/18-06sc-linear-algebra-fall-2011/least-squares-determinants-and-eigenvalues/projections-onto-subspaces/
	 * MIT18_06SCF11_Ses2.2sum.pdf
	 * 
	 * @param p
	 * @return
	 */

	@Override
	public Shape project(final Shape o) {
		final Shape project = line.project(o);
		return describeRelation(project)==RELATION_ON_LINE_SEGMENT ? project : null;
	}

}
